Skip to content

feat(cli): add --output json/yaml to sandbox get, status, and sandbox create#1989

Merged
elezar merged 3 commits into
NVIDIA:mainfrom
rhuss:feat/cli-structured-output
Jul 24, 2026
Merged

feat(cli): add --output json/yaml to sandbox get, status, and sandbox create#1989
elezar merged 3 commits into
NVIDIA:mainfrom
rhuss:feat/cli-structured-output

Conversation

@rhuss

@rhuss rhuss commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Summary

Add --output json/yaml to sandbox get, status, and sandbox create so automation and MCP tool wrappers can consume structured data instead of parsing ANSI-colored human output.

Related Issue

Closes #1964

Changes

  • sandbox get --output json/yaml: New sandbox_detail_to_json converter enriches the existing sandbox_to_json with policy source, revision, and active policy content from GetSandboxConfigResponse. Uses sandbox_policy_to_json_value for direct proto-to-JSON conversion.
  • status --output json/yaml: New status_to_json converter emits gateway, server, status, and conditional fields (auth, version, error, http_status). Refactored gateway_status to build data before output routing.
  • sandbox create --output json/yaml: Emits sandbox metadata after Ready phase. Human chrome (header, spinner) suppressed from stdout; progress message on stderr. Uploads and port forwarding still execute before output. Clap rejects --output combined with --editor or trailing commands.
  • No-gateway path: status --output json with no configured gateway emits {"status": "not_configured"} instead of human text.
  • All three commands reuse the existing OutputFormat enum and print_output_single helper.
  • Default output (no --output flag) is byte-identical to current behavior (verified by diffing raw ANSI output).
  • Docs updated for sandbox get, sandbox create, and status in manage-sandboxes.mdx and manage-gateways.mdx.

Testing

  • cargo clippy clean, cargo fmt clean
  • 188 unit tests pass (cargo test --lib)
  • 5 new unit tests for sandbox_detail_to_json and status_to_json converters
  • Integration test call sites updated for new function signatures
  • Smoke-tested against live local gateway: sandbox get --output json, status --output json/yaml, default output byte-identical regression check
  • Deep review (5 agents + CodeRabbit + Copilot): all Critical/Important findings fixed

Checklist

  • Follows Conventional Commits
  • Commits are signed off (DCO)
  • Architecture docs updated (if applicable)

@rhuss
rhuss requested review from a team, derekwaynecarr, maxamillion and mrunalp as code owners June 24, 2026 16:32
@copy-pr-bot

copy-pr-bot Bot commented Jun 24, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@github-actions

github-actions Bot commented Jun 24, 2026

Copy link
Copy Markdown

All contributors have signed the DCO ✍️ ✅
Posted by the DCO Assistant Lite bot.

@rhuss

rhuss commented Jun 24, 2026

Copy link
Copy Markdown
Contributor Author

I have read the DCO document and I hereby sign the DCO.

@rhuss

rhuss commented Jun 24, 2026

Copy link
Copy Markdown
Contributor Author

recheck

@johntmyers johntmyers self-assigned this Jun 24, 2026
Comment thread crates/openshell-cli/src/run.rs Outdated
Comment thread crates/openshell-cli/src/run.rs Outdated
@rhuss
rhuss force-pushed the feat/cli-structured-output branch from 1816278 to 9aa0ec4 Compare June 25, 2026 04:29
@rhuss

rhuss commented Jun 25, 2026

Copy link
Copy Markdown
Contributor Author

@johntmyers thanks for the review! As I'm on my way to dive into the codebase I will try to understand the codebase a bit better (not a Rust coder yet). But I think your comment ironically also hint to a problmen that this PR tries to partially solve: We need to be careful currently around the wording of log/error messages as they are parsed and used for result evaluation (i know at least one tool that wraps that parses the output of sandbox instead of using the SDK directly).

Therefor having the option for a structured output make much sense for these use cases. I wonder though, whether one should keep stderr free for informal messages or whether not (if -o json) is given also the error messages should be structured (I tend to the later). What's your take on this ?

@rhuss

rhuss commented Jun 25, 2026

Copy link
Copy Markdown
Contributor Author

I'll create a follow-up issue for emitting structured JSON errors when --output json/yaml is active, so automation consumers get parseable error responses instead of miette-formatted text. That's a broader change touching the error handling in main() and should cover all commands, not just the three in this PR.

@rhuss

rhuss commented Jun 29, 2026

Copy link
Copy Markdown
Contributor Author

All comments resolved, what do I need to trigger the CI ? 🙏

@rhuss

rhuss commented Jun 29, 2026

Copy link
Copy Markdown
Contributor Author

I'll create a follow-up issue for emitting structured JSON errors when --output json/yaml is active, so automation consumers get parseable error responses instead of miette-formatted text. That's a broader change touching the error handling in main() and should cover all commands, not just the three in this PR.

--> #2040

@rhuss
rhuss force-pushed the feat/cli-structured-output branch from d287542 to a0a287f Compare June 30, 2026 07:14
elezar
elezar previously requested changes Jul 10, 2026

@elezar elezar left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requesting changes because structured output does not currently guarantee clean stdout.

When --output json or --output yaml is selected, display is set to None. However, handle_platform_progress_event() interprets None as non-interactive/plain output and prints completed steps and details with println!(). If provisioning emits a progress event, stdout will contain human-readable lines before the final JSON/YAML document, making it invalid for automation.

Please:

  • Introduce an explicit structured progress mode that is silent or writes only to stderr.
  • Reserve stdout exclusively for the final JSON/YAML document.
  • Add integration coverage that emits provisioning progress, captures the complete stdout from sandbox create --output json/yaml, and successfully parses it.

I recommend modeling interactive, plain, and structured progress as explicit variants rather than using Option<ProvisioningDisplay>. The full presenter refactor is not required to unblock this PR; the blocking requirement is that structured stdout remains parseable under all provisioning event paths.

@rhuss
rhuss force-pushed the feat/cli-structured-output branch from baee9b4 to 22b16cb Compare July 14, 2026 13:25
@rhuss

rhuss commented Jul 14, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the review. All four points are addressed:

1. Explicit structured progress mode (commit 22b16cbd): Option<ProvisioningDisplay> is replaced with an explicit ProgressOutput enum with three variants: Interactive, Plain, and Silent. Structured output mode uses Silent.

2. Stdout reserved for final JSON/YAML (commit 22b16cbd): In Silent mode, handle_platform_progress_event() is a no-op. All informational messages during provisioning go to stderr via eprintln!(). Stdout is reserved exclusively for the final JSON/YAML document.

3. Integration coverage (commit 644677e3): Added two integration tests (sandbox_create_json_output_succeeds_with_progress_events and sandbox_create_yaml_output_succeeds_with_progress_events) that exercise the full provisioning flow with progress events while --output json/yaml is active. These confirm the Silent code path works end-to-end. Full stdout-capture-and-parse assertions would require either a _to_writer refactor of sandbox_create (similar to sandbox_policy_get_to_writer) or adding an stdout capture dependency, both of which seemed like scope creep for this PR.

4. Replace Option<ProvisioningDisplay> (commit 22b16cbd): Done, as described in point 1.

@rhuss

rhuss commented Jul 22, 2026

Copy link
Copy Markdown
Contributor Author

@elezar Gentle ping - the feedback from your review has been addressed in commit 22b16cbd (explicit ProgressOutput enum replacing Option<ProvisioningDisplay>). Would you have a chance to take another look?

@elezar

elezar commented Jul 22, 2026

Copy link
Copy Markdown
Member

@rhuss I think this looks better now. Do you mind rebasing so that we can complete the review? (I have a added a test-only commit on top that you can include in your changes as you see fit).

@rhuss
rhuss force-pushed the feat/cli-structured-output branch 2 times, most recently from 5c4f020 to 7c16a74 Compare July 23, 2026 08:19
@rhuss

rhuss commented Jul 23, 2026

Copy link
Copy Markdown
Contributor Author

@elezar rebased on upstream/main and squashed to a single commit to clean up a bit (otherwise a lot of back and forth between the various commits, mostly because of several rebasing rounds).

Let me know if something is still missing.

… create

Add structured output support (JSON and YAML) to sandbox lifecycle
commands: sandbox get, status, and sandbox create.

Introduce ProgressOutput enum to cleanly separate interactive,
plain, and silent display modes during sandbox provisioning.

Signed-off-by: Roland Huß <rhuss@redhat.com>
@rhuss
rhuss force-pushed the feat/cli-structured-output branch from 7c16a74 to 212217a Compare July 24, 2026 06:27
Signed-off-by: Evan Lezar <elezar@nvidia.com>
@elezar

elezar commented Jul 24, 2026

Copy link
Copy Markdown
Member

/ok-to-test 212217a

Signed-off-by: Evan Lezar <elezar@nvidia.com>
@elezar

elezar commented Jul 24, 2026

Copy link
Copy Markdown
Member

Pushed two small follow-up fixes:

  • sandbox create --output now conflicts with side-effect modes (--editor, trailing commands, --no-keep, and --forward) and has table-driven parser coverage.
  • Upload SSH transport now discards child stdout unconditionally so successful uploads cannot pollute structured stdout; stderr remains inherited for diagnostics.

Possible follow-ups:

  • Add first-class --output + --forward support by detaching/capturing the background SSH process and including forward metadata in the JSON/YAML payload.
  • If we want stronger upload guarantees, add an integration test for noisy SSH stdout or capture upload stdout and surface it only on failure.

@elezar

elezar commented Jul 24, 2026

Copy link
Copy Markdown
Member

/ok-to-test 0a91547

@elezar
elezar dismissed their stale review July 24, 2026 09:41

Changes applied.

@elezar elezar left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the patience here @rhuss.

@elezar
elezar enabled auto-merge July 24, 2026 09:41
@elezar elezar added the test:e2e Requires end-to-end coverage label Jul 24, 2026
@github-actions

Copy link
Copy Markdown

Label test:e2e applied for 0a91547. Open the existing run and click Re-run all jobs to execute with the label set. The run will execute the standard E2E suite after building the required gateway and supervisor images once. The matching required CI gate status on this PR will flip green automatically once the run finishes.

@elezar

elezar commented Jul 24, 2026

Copy link
Copy Markdown
Member

@rhuss please resolve the comments that have been addressed. This should merge the PR.

@elezar
elezar added this pull request to the merge queue Jul 24, 2026
Merged via the queue into NVIDIA:main with commit b422b67 Jul 24, 2026
66 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

test:e2e Requires end-to-end coverage

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Extend --output json to sandbox list, sandbox create, and status commands

3 participants